﻿using System;
using System.Security.Cryptography;
using System.Threading.Tasks;
using Devonline.Core;
using Devonline.Entity;
using Devonline.Http;
using Devonline.Identity;
using Mapster;
using Microsoft.AspNetCore.Authentication.Cookies;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Logging;
using ProjectManagement.Models;

namespace ProjectManagement.Controllers
{
    [Route("api/[controller]")]
    [ApiController]
    [Authorize(AuthenticationSchemes = CookieAuthenticationDefaults.AuthenticationScheme)]
    public class UsersController : ControllerBase
    {
        private readonly AppSetting _appSetting;
        private readonly ApplicationDbContext _context;
        private readonly ILogger<UsersController> _logger;

        public UsersController(ApplicationDbContext context, ILogger<UsersController> logger, AppSetting appSetting)
        {
            _context = context;
            _logger = logger;
            _appSetting = appSetting;
        }

        [HttpGet]
        public async Task<IActionResult> GetAsync()
        {
            var users = await _context.Users.ToListAsync();
            if (users.IsNotNullOrEmpty())
            {
                users.ForEach(x => x.PasswordHash = null);
            }

            return Ok(users);
        }

        /// <summary>
        /// 用户新增使用默认密码
        /// </summary>
        /// <param name="entitySet"></param>
        /// <returns></returns>
        [HttpPost]
        public async Task<IActionResult> Post([FromBody] UserModel entitySet)
        {
            if (entitySet == null)
            {
                throw new Exception($"{typeof(User).GetDisplayName()} 不能为空!");
            }

            await _context.UniqueAsync<User, string>(entitySet);
            entitySet.PasswordHash = _appSetting.DefaultPassword.GetHashCode<SHA256>();
            entitySet.Create();
            entitySet.Update();

            //处理附件, 无附件则不用写下面的代码及删除文件的代码
            await _context.AddAttachmentsAsync<User>(entitySet, entitySet.Attachments);

            _context.Add(entitySet);
            await _context.SaveChangesAsync().ConfigureAwait(true);
            entitySet.PasswordHash = null;
            return Ok(entitySet);
        }

        /// <summary>
        /// 用户修改忽略密码字段
        /// </summary>
        /// <param name="key"></param>
        /// <param name="entitySet"></param>
        /// <returns></returns>
        [HttpPut("{key}")]
        public async Task<IActionResult> Put(string key, [FromBody] UserModel entitySet)
        {
            var displayName = typeof(User).GetDisplayName();
            if (entitySet == null)
            {
                throw new Exception($"{displayName} 不能为空!");
            }

            var entity = await _context.Users.FindAsync(key);
            if (entity == null)
            {
                throw new Exception($"{displayName} 中当前记录不存在!");
            }

            await _context.UniqueAsync<User, string>(entitySet);

            var config = new TypeAdapterConfig();
            config.ForType<User, User>().Ignore(x => x.Id, x => x.RowVersion, x => x.PasswordHash);
            entitySet.Adapt(entity, config);
            entity.Update();

            //处理附件, 无附件则不用写下面的代码及删除文件的代码
            var files = await _context.UpdateAttachmentsAsync<User, Attachment, string>(entitySet, entitySet.Attachments, nameof(User) + AppSettings.CHAR_DOT + nameof(entitySet.Image));

            _context.Update(entity);
            await _context.SaveChangesAsync().ConfigureAwait(true);
            files.Delete(_logger);
            return Ok(entity);
        }

        [HttpDelete("{key}")]
        public async Task<IActionResult> Delete(string key)
        {
            var entitySet = await _context.Users.FindAsync(key);
            if (entitySet == null)
            {
                throw new Exception($"{typeof(User).GetDisplayName()} 中当前记录不存在!");
            }

            //处理附件, 无附件则不用写下面的代码及删除文件的代码
            var files = await _context.DeleteAttachmentsAsync<Attachment, string>(entitySet.Id);

            _context.Remove(entitySet);
            await _context.SaveChangesAsync().ConfigureAwait(true);
            files.Delete(_logger);
            return Ok();
        }
    }
}
